package com.uxsino.simo.indicator;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.uxsino.reactorq.model.INDICATOR_TYPE;
import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryContext;

public class ExprIndicator extends IndicatorWithRefer implements IExprItem, INoneQueryIndicator {

    private static Logger logger = LoggerFactory.getLogger(ExprIndicator.class);

    protected INDICATOR_TYPE returnType;

    protected String formula;

    @JsonIgnore
    private Object compiled;

    @JsonIgnore
    private boolean exprDisabled = false;

    @JsonIgnore
    @SuppressWarnings("rawtypes")
    private Map<String, Class> referredVariables;

    public Set<String> referredNames = new HashSet<>(5);

    public ExprIndicator(String indicatorName, INDICATOR_TYPE returnType, String formula) {
        super(indicatorName);
        this.returnType = returnType;
        this.formula = formula;
    }

    @Override
    public INDICATOR_TYPE getIndicatorType() {
        return returnType;
    }

    @Override
    public void setFormula(String formula) {
        this.formula = formula;
    }

    @Override
    public String getFormula() {
        return formula;
    }

    @Override
    public void doPostQuery(EntityInfo entity, QueryContext ctxt, Object value) {
        Object v;
        long time = System.currentTimeMillis();
        try {
            v = ctxt.getExprEvaluator(entity).evalExprIndicator(this);
            v = castValue(v, this.returnType);
        } catch (Exception e) {
            logger.error("error evaluating expr indicator {}. {}", this.name, e);
            ctxt.setIndicatorFail(entity.id, this.name);
            return;
        }
        ctxt.setIndicatorValue(entity, this, 0, v, System.currentTimeMillis() - time);
    }

    @Override
    public Object getCompiled() {
        return compiled;
    }

    @Override
    public void setCompiled(Object compiled) {
        this.compiled = compiled;
    }

    @Override
    public void setReferredVariables(@SuppressWarnings("rawtypes") Map<String, Class> refs) {
        this.referredVariables = refs;

        referredVariables.forEach((name, cls) -> {
            referedIndicatorNames.add(name);
        });
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Map<String, Class> getReferredVariables() {
        return this.referredVariables;
    }

    @Override
    public void disable() {
        exprDisabled = true;
    }

    @Override
    public boolean isDisabled() {
        return exprDisabled;
    }

}
